package internal

import (
	"bytes"
	"errors"
	"fmt"
	"math"
	"math/rand/v2"
	"sync"
	"unsafe"
)

type BytesBuffer struct {
	pool sync.Pool
	cap  int
}

func NewBytesBuffer(defaultCap ...int) *BytesBuffer {
	p := &BytesBuffer{
		pool: sync.Pool{},
	}
	if len(defaultCap) > 0 && defaultCap[0] > 0 {
		p.cap = defaultCap[0]
	}
	p.pool.New = func() any {
		if p.cap > 0 {
			return bytes.NewBuffer(make([]byte, 0, p.cap))
		}
		return new(bytes.Buffer)
	}
	return p
}

// 获取字节数组
func (p *BytesBuffer) Get() *bytes.Buffer {
	return p.pool.Get().(*bytes.Buffer)
}

// 归还字节数组
func (p *BytesBuffer) Put(b *bytes.Buffer) {
	if b == nil {
		return
	}
	// 重置已用大小
	b.Reset()
	p.pool.Put(b)
}

const (
	hashFnvOffset32 uint32 = 2166136261
	hashFnvPrime32  uint32 = 16777619
)

func HashFnv32(key string) uint32 {
	if key == "" {
		return hashFnvOffset32
	}
	hash := hashFnvOffset32
	for i := 0; i < len(key); i++ {
		hash ^= uint32(key[i])
		hash *= hashFnvPrime32
	}
	return hash
}

// PowerOf2 函数用于检查并返回给定分片数量 count 的最小值，该值必须是2的幂，并且不超过4096。
func PowerOf2(count uint32) uint32 {
	if count <= 2 {
		return 2
	}
	// 找到大于等于count的最小2的幂
	count--
	count |= count >> 1
	count |= count >> 2
	count |= count >> 4
	count |= count >> 8
	count |= count >> 16
	count++
	// 限制最大值为4096
	if count > 4096 {
		return 4096
	}
	return count
}

// randTables 62
//   - tableLenth:62 maskBits: 6, maskVal: 63, maskMax: 10
var randTables = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func RandString(length int) string {
	if length <= 0 {
		return ""
	}
	randomBytes := make([]byte, length)
	for i, cache, next := length-1, rand.Uint64(), 10; i >= 0; {
		if next == 0 {
			cache, next = rand.Uint64(), 10
		}
		if idx := cache & 63; idx < 62 {
			randomBytes[i] = randTables[idx]
			i--
		}
		cache >>= 6
		next--
	}
	return unsafe.String(unsafe.SliceData(randomBytes), length)
}
func RandAppend(target *[]byte) error {
	if target == nil {
		return errors.New("cache: RandAppend, target must be *[]byte, got a nil")
	}
	if cap(*target) < 1 {
		return errors.New("cache: RandAppend, target capacity too small")
	}
	if len(*target) == cap(*target) {
		return errors.New("cache: RandAppend, target is full")
	}

	length := cap(*target) - len(*target)
	for i, cache, next := length-1, rand.Uint64(), 10; i >= 0; {
		if next == 0 {
			cache, next = rand.Uint64(), 10
		}
		if idx := cache & 63; idx < 62 {
			*target = append(*target, randTables[idx])
			i--
		}
		cache >>= 6
		next--
	}
	return nil
}

const (
	unitKB = 1024
	unitMB = unitKB * 1024
	unitGB = unitMB * 1024
	unitTB = unitGB * 1024
)

// FormatSize 转换字节数大小为代TB/GB/MB/KB/Byte单位语义或字符串表示形式
func FormatSize(byteSize int64) string {
	switch {
	case byteSize >= unitTB:
		return fmt.Sprintf("%.2f TB", formatSizeTrunc(byteSize, unitTB))
	case byteSize >= unitGB:
		return fmt.Sprintf("%.2f GB", formatSizeTrunc(byteSize, unitGB))
	case byteSize >= unitMB:
		return fmt.Sprintf("%.2f MB", formatSizeTrunc(byteSize, unitMB))
	case byteSize >= unitKB:
		return fmt.Sprintf("%.2f KB", formatSizeTrunc(byteSize, unitKB))
	default:
		return fmt.Sprintf("%d Byte", byteSize)
	}
}
func formatSizeTrunc(byteSize int64, unitSize int) float64 {
	return math.Trunc(float64(byteSize)/float64(unitSize)*100) / 100
}
